/*
 * Daemon.java
 *
 * Created on April 19, 2006, 7:20 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */


package Comm.Util;

import Comm.Net.BaseData;
import Comm.Net.GetData;
import Comm.Net.LogPostData;
import Comm.Net.NetThread;
import Comm.Net.SamplePostData;
import Experience.ExpUI;
import Experience.FollowupSample;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Timer;

import java.util.TimerTask;
import java.util.Vector;

/**
 *
 * @author dmgreen
 */
public class MaintenanceTask extends TimerTask {
   
    private Hashtable mySampleData = null;
    private int myCounter = 0;
    
    public MaintenanceTask(Hashtable samples) {
        mySampleData = samples;
    }
    
    public void run() {
       
        log ("Performing maintenence task ... ", Logger.MSG_DEBUG);
        
        int thread_count = Thread.activeCount();
        //log ("IN maintenence task; thread count is " + thread_count);
       
        int num_samples = mySampleData.size();
        if (num_samples > 0) {
            log("There are " + num_samples + " pending samples in the queue", Logger.MSG_DEBUG);
        } else {
            log("There are no pending samples in the queue at this time", Logger.MSG_DEBUG);
        }
        
        myCounter++;
        //log ("myCounter is " + myCounter);
           
        Vector enum_vector = new Vector();
        Enumeration en = mySampleData.elements();
        while (en.hasMoreElements()) {
            enum_vector.addElement(en.nextElement());
        }
        en = null;
        
        Enumeration samples_enum = enum_vector.elements();
        
        while (samples_enum.hasMoreElements()) {
            
            // pretty confusing here.
            // can be either a BaseData derivative or a BaseSanple (followupsample)
            
            Object ob = samples_enum.nextElement();
            
            BaseData bd = null;
            try {
                bd = (BaseData) ob;
            } catch (ClassCastException cce) {
                /* This will happen if it's a followupsample.
                 * If it is, this code will replace the followupsample in the map with a 
                 * FollowupPostObject. And this will be removed once it has been sent.
                 **/
                continue;
            }

            //BaseData bd = (BaseData) samples_enum.nextElement(); 
        
            if (bd.getStatus() == BaseData.SENT) {
                log("Looks like sample #" + bd.getUID() + " has been SENT ... removing", Logger.MSG_DEBUG);
            
                if (bd.getMsgType() == BaseData.MSGTYPE_TAG) {
                    Logger.getLog().addLogMessage("Found a tag message!", Logger.MSG_DEBUG);
                    ExpUI.getMIDlet().getTagManager().synchTags(bd.getResponse());
                    mySampleData.remove(new Integer(bd.getUID()));
                } else if (bd.getMsgType() == BaseData.MSGTYPE_FOLLOWUP) { 
                    Logger.getLog().addLogMessage("Found a followup message!", Logger.MSG_DEBUG);
                    mySampleData.remove(new Integer(bd.getUID()));
                    
                }  else if (bd.getMsgType() == BaseData.MSGTYPE_LOG) { 
                    Logger.getLog().addLogMessage("Found a log message!", Logger.MSG_DEBUG);
                    mySampleData.remove(new Integer(bd.getUID()));
                    
                } else if (bd.getMsgType() == BaseData.MSGTYPE_SAMPLE) {
                    Logger.getLog().addLogMessage("Found a sample", Logger.MSG_DEBUG);
                    
                    // used to be two hours == 7200000
                    // two minutes = 120000
                    if ( (System.currentTimeMillis() - bd.getSendTime()) >= 7200000) {
                        Logger.getLog().addLogMessage("Initiating followup sample", Logger.MSG_DEBUG);
                        int corr_sample_id = parseSampleID(bd.getResponse());
                        if (corr_sample_id >= 0) {
                            
                            // CREATE A NEW FOLLOWUP HERE, and PASS AROUND REFERENCE!
                            FollowupSample fs = new FollowupSample( corr_sample_id, 
                                                                    bd.getUID(),
                                                                   ((SamplePostData) bd).getSampleGlucose(),
                                                                    ((SamplePostData) bd).getSampleImage() 
                                                                    );
                            
                            // here the followup SAMPLE gets put in and not the corresponding data object....
                            mySampleData.put(new Integer(bd.getUID()), fs);
                            
                            if (ExpUI.getMIDlet().getCurrentSample() == null) {
                                ExpUI.getMIDlet().startNewFollowup(bd.getUID());
                            } else {
                                (new Timer()).schedule(new FollowupTask(bd.getUID()), 180000);
                            } // END if current sample is null
                        } else { // END if id parsing failed (-1)
                             mySampleData.remove(new Integer(bd.getUID()));
                        }
                    
                    } // END if it's  been more than two hours 
                } // END if message is a sample
            }
           
            
            else if (bd.getStatus() == BaseData.FAILED) {
                log("Looks like sample #" + bd.getUID() + " has FAILED ... resending", Logger.MSG_DEBUG);
                NetThread nt = new NetThread(bd);
                nt.start();
            } 
            else if (bd.getStatus() == BaseData.UNSENT) {
                // don't do anything ... this means it hasn't been touched yet
                // and there is just a funny timing issue.
            }
        }
        
        
           // i.e. once every ten minutes by 18 cycles == three hours
        if (myCounter % 18 == 0) {
             log("Pinging server with a log message", Logger.MSG_DEBUG);
            LogPostData lp = new LogPostData();
            lp.addLog("THIS IS A LOG!!");
            mySampleData.put(new Integer(lp.getUID()), lp);
            NetThread nt = new NetThread(lp);
            nt.start();
        }
        
        // updates tags every half hour!!
        
        //if (myCounter % 3 == 0) {
        if (true) {    // try to update tags ore often, every 10 min
            log("Updating tags", Logger.MSG_DEBUG);
            GetData gd = new GetData(ExpUI.TAG_UPDATER_URL);
            gd.setMsgType(BaseData.MSGTYPE_TAG);
            mySampleData.put(new Integer(gd.getUID()), gd);
            NetThread nt = new NetThread(gd);
            nt.start();
            
            // need to tell netthread to call a certain function in TagManager if it
            // successfully downloads tags.
        }    
    }
    
    public void log(String msg, String msg_mode) {
        Logger.getLog().addLogMessage(msg, msg_mode);
    }
    
    private int parseSampleID(String sample_id_str) {
        if ( ! sample_id_str.substring(0,3).equals("ID:")) {
            Logger.getLog().addLogMessage("Couldn't parse id from \"" + sample_id_str + "\"", Logger.MSG_ERROR);
            return -1;
        }
        
        String id_str = "";
        int id_int = -1;
        try {
            id_str = sample_id_str.substring(3);
            id_int = Integer.parseInt(id_str);
        } catch (IndexOutOfBoundsException ioobe) {
            Logger.getLog().addLogMessage("OutOfBounds: Couldn't parse id from \"" + sample_id_str + "\"", Logger.MSG_ERROR);
            return -1;
        } catch (NumberFormatException nfe) {
            Logger.getLog().addLogMessage("NumberFormat: Couldn't parse id from \"" + sample_id_str + "\"", Logger.MSG_ERROR);
            return -1;
        }
        
        return id_int;
    }
    
}


